package jp.go.aist.six.vuln.repository.scap.nvd;

import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.List;
import jp.go.aist.six.util.xml.XmlMapper;
import jp.go.aist.six.vuln.NvdDataFeed;
import jp.go.aist.six.vuln.core.VulnContext;
import jp.go.aist.six.vuln.model.scap.nvd.Nvd;
import jp.go.aist.six.vuln.model.scap.vulnerability.VulnerabilityType;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;


//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration( locations="classpath:jp/go/aist/six/vuln/core/six-vuln_context.xml" )
@Ignore( "Use of QueryDSL is pending." )
@RunWith( Enclosed.class )
public class NvdVulnerabilityRepositoryTest
{

//    @Autowired
    protected XmlMapper  _xml_mapper;


//    @Autowired
    protected NvdVulnerabilityRepository  _repository;


    protected void _init(
                    final String tmp_subdir
                    )
    {
        _xml_mapper = VulnContext.server().getXmlMapper();
        _repository = VulnContext.server().getBean( NvdVulnerabilityRepository.class );
    }


    /**
     */
    @RunWith( Theories.class )
    public static class LocalFile
    extends NvdVulnerabilityRepositoryTest
    {

        @Before
        public void setUp()
        {
            _init( "local-file" );
        }


        @DataPoints
        public static String[] nvdDataFeedDirs()
        {
            return NvdDataFeed.FILE_DIRS;
        }


        @Ignore( "use NvdDataFeedInstaller test" )
        @Theory
        public void testSave(
                        final String dir_path
                        )
        throws Exception
        {
            for (String  file_name : NvdDataFeed.FILE_NAMES) {
                File  in_xml_file = new File( dir_path, file_name );
                System.out.println( "NVD Data Feed file: " + in_xml_file );
                if (!in_xml_file.exists()) {
                    System.out.println( "SKIP: NVD Data Feed (NOT found): " + file_name );
                }

                System.out.println( "unmarshalling NVD Data Feed..." );
                Nvd  nvd = _xml_mapper.unmarshal( new FileInputStream( in_xml_file ), Nvd.class );
                System.out.println( "...unmarshalling DONE" );

                String  pubDate = nvd.getPubDate();
                System.out.println( "  - pub_date=" +  pubDate );
                System.out.println( "  - nvd_xml_version=" + nvd.getNvdXmlVersion() );
                System.out.println( "  - #entries=" + nvd.getEntry().size() );

                _repository.save( nvd.getEntry() );
//                for (VulnerabilityType  v : nvd.getEntry()) {
//                    System.out.println( "saving vulnerability: id=" + v.getId() );
//                    _repository.save( v );
//                }

                System.out.println( "...save COMPLETED" );
            }
        }
    }


    /**
     */
    @RunWith( JUnit4.class )
    public static class Query
    extends NvdVulnerabilityRepositoryTest
    {

        @Before
        public void setUp()
        {
            _init( "crud" );
        }


        @Test
        public void testCount()
        {
            long  count = _repository.count();
            System.out.println( "count=" + count );
        }


        @Test
        public void testFindById()
        {
            List<String>  id_list = Arrays.asList( new String[] {
                            "CVE-2013-0001",
                            "CVE-2013-0002"
                            } );

            for (String  id : id_list) {
                System.out.println( "finding by ID=" + id );
                VulnerabilityType  v = _repository.findOne( id );
                System.out.println( "vulnerability=" + v );
            }

            System.out.println( "finding by IDs=" + id_list );
            Iterable<VulnerabilityType>  i = _repository.findAll( id_list );
            for (VulnerabilityType  v : i) {
                System.out.println( "vulnerability=" + v.getId() );
//                System.out.println( "vulnerability=" + v );
            }
        }


        @Test
        public void testFindByCveId()
        {
            String  cve = "CVE-2013-0601";
            System.out.println( "finding by CVE=" + cve );
            VulnerabilityType  v = _repository.findByCveId( cve );
            System.out.println( "vulnerability=" + v.getCveId() );
//            System.out.println( "vulnerability=" + v );
        }



//        @Test
//        public void testFindAllQueryByAffectedProduct()
//        {
//            String  cpe = "cpe:/a:adobe:acrobat:9.5.2";
//            System.out.println( "query: product cpe=" + cpe );
//
//            QVulnerabilityType  query = QVulnerabilityType.vulnerabilityType;
//            Iterable<VulnerabilityType>  result = _repository.findAll( query.vulnerableSoftwareList.product.contains( cpe ) );
//
//            for (VulnerabilityType  v : result) {
//                Collection<String>  products = v.getVulnerableSoftwareList().getProduct();
//                System.out.println( v.getId() );
////                System.out.println( "  vulnerability: id=" + v.getId() + ", vulnerableSoftwareList=" + products );
//                assertThat( "contains product", products, hasItem( cpe ) );
//            }
//            System.out.println( "...query COMPLETED" );
//        }
//
//
//
//        @Test
//        public void testFindAllQueryByAffectedProductPattern()
//        {
//            String  cpe = "cpe:/a:adobe:acrobat:10";
//            System.out.println( "query: product cpe=" + cpe );
////            QVulnerableSoftwareType  q_soft = QVulnerableSoftwareType.vulnerableSoftwareType.product.
//
//            QVulnerabilityType  query = QVulnerabilityType.vulnerabilityType;
//            Iterable<VulnerabilityType>  result = _repository.findAll(
//                            query.vulnerableSoftwareList.product.any().startsWith( cpe ) );
//            // LIKE "cpe%"
//
//            for (VulnerabilityType  v : result) {
//                System.out.println( v.getId() );
////              Collection<String>  products = v.getVulnerableSoftwareList().getProduct();
////                System.out.println( "  vulnerability: id=" + v.getId() + ", vulnerableSoftwareList=" + products );
//            }
//            System.out.println( "...query COMPLETED" );
//        }

    }


//    @Test
//    public void testFindAllByCWE
//    throws Exception
//    {
//        String  cwe = "CWE-79";
//        System.out.println( "query: CWE id=" + cwe );
//
//        CweReferenceType  cwe_ref = new CweReferenceType( cwe );
//        QVulnerabilityType  query = QVulnerabilityType.vulnerabilityType;
//        Iterable<VulnerabilityType>  result = _repository.findAll( query.cwe.contains( cwe_ref ) );
//
//        for (VulnerabilityType  v : result) {
//            System.out.println( "  vulnerability: id=" + v.getId() );
//            assertThat( "contains CWE", v.getCwe(), hasItem( cwe_ref ) );
//        }
//        System.out.println( "...query COMPLETED" );
//    }

}
//
